#pragma once

#include <memory>
#include <optional>
#include <set>
#include <unordered_map>
#include <vector>

#include "NativeModule.h"
#include "utils/Dynamic.h"

namespace jsiexecutor {
struct ModuleConfig {
  std::string moduleName;
  size_t moduleID;
  std::unordered_map<std::string, size_t> methods;
  std::set<size_t> syncMethodIds;
  Dynamic constants;
};
class ModuleRegistry {
 public:
  ModuleRegistry(std::vector<std::unique_ptr<NativeModule>> modules) : modules_(std::move(modules)) {};

  void registerModules(std::vector<std::unique_ptr<NativeModule>> modules);

  std::optional<ModuleConfig> getConfig(const std::string& name);

  void callNativeMethodSync(unsigned int moduleId, unsigned int methodId, std::vector<Dynamic>& params);

  void callNativeMethodAsync(unsigned int moduleId, unsigned int methodId, std::vector<Dynamic>& params,
                             unsigned int callbackId);

 private:
  std::vector<std::string> moduleNames();

  std::vector<std::unique_ptr<NativeModule>> modules_;
  std::unordered_map<std::string, size_t> modulesByName_;
};

}  // namespace jsiexecutor
